package nosqls

import (
	"context"
	"fmt"

	"github.com/redis/go-redis/extra/redisotel/v9"
	redis "github.com/redis/go-redis/v9"
)

// configureRedisClient 统一配置Redis客户端的通用功能
// 包括连接测试、追踪和指标收集
func configureRedisClient(client RedisClient, config *RedisConfig) error {
	// 1. 测试连接
	if err := client.Ping(context.Background()).Err(); err != nil {
		return fmt.Errorf("failed to connect Redis: %v", err)
	}

	// 2. 根据配置启用追踪
	if config.EnableTracing {
		switch c := client.(type) {
		case *redis.Client:
			if err := redisotel.InstrumentTracing(c); err != nil {
				return fmt.Errorf("failed to instrument Redis tracing: %v", err)
			}
		case *redis.ClusterClient:
			if err := redisotel.InstrumentTracing(c); err != nil {
				return fmt.Errorf("failed to instrument Redis cluster tracing: %v", err)
			}
		}
	}

	// 3. 根据配置启用指标收集
	if config.EnableMetrics {
		switch c := client.(type) {
		case *redis.Client:
			if err := redisotel.InstrumentMetrics(c); err != nil {
				return fmt.Errorf("failed to instrument Redis metrics: %v", err)
			}
		case *redis.ClusterClient:
			if err := redisotel.InstrumentMetrics(c); err != nil {
				return fmt.Errorf("failed to instrument Redis cluster metrics: %v", err)
			}
		}
	}

	return nil
}

// RedisSingleConfig Redis单节点配置
type RedisSingleConfig RedisConfig

// RedisSentinelConfig Redis哨兵配置
type RedisSentinelConfig RedisConfig

// RedisClusterConfig Redis集群配置
type RedisClusterConfig RedisConfig

// 确保所有配置类型都实现了 InitNosqlter 接口
var _ InitNosqlter = (*RedisSingleConfig)(nil)
var _ InitNosqlter = (*RedisSentinelConfig)(nil)
var _ InitNosqlter = (*RedisClusterConfig)(nil)

// InitRedis 初始化Redis单节点连接并返回 *redis.Client
func (d *RedisSingleConfig) InitRedis() RedisClient {
	client := redis.NewClient(&redis.Options{
		Addr:     d.Address[0],
		Username: d.Username,
		Password: d.Password,
		DB:       d.Database,
	})

	// 使用统一的配置函数
	config := (*RedisConfig)(d)
	if err := configureRedisClient(client, config); err != nil {
		panic(err)
	}

	return client
}

// InitRedis 初始化Redis哨兵连接并返回 *redis.Client
func (d *RedisSentinelConfig) InitRedis() RedisClient {
	client := redis.NewFailoverClient(&redis.FailoverOptions{
		MasterName:    d.MasterName,
		SentinelAddrs: d.Address,
		Username:      d.Username,
		Password:      d.Password,
		DB:            d.Database,
	})

	// 使用统一的配置函数
	config := (*RedisConfig)(d)
	if err := configureRedisClient(client, config); err != nil {
		panic(err)
	}

	return client
}

// InitRedis 初始化Redis集群连接并返回 *redis.ClusterClient
func (d *RedisClusterConfig) InitRedis() RedisClient {
	client := redis.NewClusterClient(&redis.ClusterOptions{
		Addrs:    d.Address,
		Username: d.Username,
		Password: d.Password,
	})

	// 使用统一的配置函数
	config := (*RedisConfig)(d)
	if err := configureRedisClient(client, config); err != nil {
		panic(err)
	}

	return client
}
